package edu.hawaii.halealohacli.command;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.resource.source.jaxb.Source;
import org.wattdepot.util.tstamp.Tstamp;
import edu.hawaii.halealohacli.HaleAloha;

/**
 * Sets the baseline for the source on the specified date.
 * 
 * @author calvin
 * 
 */
public class SetBaseline implements Command {

  private String command = "set-baseline";
  private String arguments = "[tower | lounge] [date]";
  private int numParams = 2;
  private Baseline baseline = null;
  private String help = "Defines [date] as the \"baseline\" day for [tower | lounge].";

  @Override
  public String run(String[] input, WattDepotClient client) {
    String output = "\"" + input[1] + "\" is not a valid source.";

    try {
      List<Source> sources = client.getSources();
      for (Source source : sources) {
        if (source.getName().equals(input[1])) {
          // Create a date format to check the date of the second argument.
          String formatString = "yyyy-MM-dd";
          SimpleDateFormat format = new SimpleDateFormat(formatString, Locale.US);
          format.setLenient(false);
          Date date = null;
          if (input.length < 3) {
            // Check if there is a date input.
            Calendar c = Calendar.getInstance();
            c.roll(Calendar.DATE, -1);
            date = format.parse(format.format(c.getTime()));
          }
          else {
            // Check if second argument is a valid date.
            date = format.parse(input[2]);
          }
          GregorianCalendar gc = new GregorianCalendar();
          DatatypeFactory dtf = DatatypeFactory.newInstance();
          XMLGregorianCalendar today = dtf.newXMLGregorianCalendar(gc);
          // Set the time to today to midnight.
          today.setTime(0, 0, 0, 0);
          // Set the date to the user input.
          gc.setTime(date);

          // Create the specified day start.
          XMLGregorianCalendar specifiedDayStart = dtf.newXMLGregorianCalendar(gc);
          // Checks if input date is a future date.
          if (today.compare(specifiedDayStart) < 0) {
            output =
                "You have entered a future date: " + format.format(gc.getTime()) + "\n"
                    + "It will be impossible to gather the data, don't you think? Try again.";
          }
          // Check if given date is the current date.
          else if (today.compare(specifiedDayStart) == 0) {
            output =
                "The given date is today's date. Currently data is being recieved until "
                    + "11:59PM\nYou can access this data tomorrow or try again and enter a date "
                    + "before today's date.";
          }
          else {
            double energy = 0;
            baseline = new Baseline(source.getName(), specifiedDayStart);

            // Added the hourly baselines to the baseline object.
            for (int i = 0; i < 24; i++) {
              specifiedDayStart.setTime(i, 0, 0, 0);
              XMLGregorianCalendar specifiedDayEnd = Tstamp.incrementMinutes(specifiedDayStart, 59);
              energy = client.getEnergyConsumed(input[1], 
                  specifiedDayStart, specifiedDayEnd, 15) / 1000;
              baseline.addBaseline(energy);
            }
            output = "The baseline has been set for " + input[1] + " on " + format.format(date);
          }
          //store each baseline call in the main HALEALOHA class
          HaleAloha.getBaseLine().put(input[1], baseline.getList());
          return output;
        }
      }
    }
    catch (NotAuthorizedException e) {
      return "Unauthorized to access the sever. Try again.";
    }
    catch (BadXmlException e) {
      return "Could not retrieve data for: " + input[1] + " on " + input[2] + "\n"
          + "It might be possible that the date entered is too back in the past. Try again.";
    }
    catch (MiscClientException e) {
      return "An error has occurred on the server.  Try again.";
    }
    catch (ResourceNotFoundException e) {
      return input[1] + " does not exist!";
    }
    catch (DatatypeConfigurationException e) {
      return "Could not format date input.";
    }
    catch (ParseException e) {
      return "\"" + input[2] + "\" is not a valid date.";
    }
    catch (IllegalArgumentException e) {
      return "\"" + input[2] + "\" is not a valid date.";
    }
    return output;
  }

  @Override
  public String getCommand() {
    return command;
  }

  @Override
  public int getNumParams() {
    return numParams;
  }

  @Override
  public String getHelp() {
    return command + " " + arguments + "\n" + help;
  }

  /**
   * Returns the baseline object.
   * 
   * @return baseline Baseline object
   */
  public Baseline getBaseline() {
    return baseline;
  }
}
